package com.company.example.interceptor;

import com.company.example.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Calendar;

@Component
@Aspect
public class MethodLogAspect {
	private static final Logger log = LoggerFactory.getLogger(MethodLogAspect.class);
	
	@Autowired
	private UserService userService;
	
	public MethodLogAspect() {
		log.info("开始日志aoplog");
	}
	
	@Pointcut("@annotation(com.company.example.interceptor.MethodLog)")
	public void methodCachePointcut() {
		
	}
	
	@Around("methodCachePointcut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {  
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E");  
        Calendar ca = Calendar.getInstance();  
        String operDate = df.format(ca.getTime());
        log.info("operDate:" + operDate);
        
        String monthRemark = getMthodRemark(point);  
        String monthName = point.getSignature().getName();  
        String packages = point.getThis().getClass().getName();  
        if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) { // 如果是CGLIB动态生成的类  
            try {  
                packages = packages.substring(0, packages.indexOf("$$"));  
            } catch (Exception ex) {  
                ex.printStackTrace();  
            }  
        }  
  
        String operatingcontent = "";  
        Object[] method_param = null;  
  
        Object object;  
        try {  
            method_param = point.getArgs(); //获取方法参数   
            // String param=(String) point.proceed(point.getArgs());  
            object = point.proceed();  
        } catch (Exception e) {  
            // 异常处理记录日志..log.error(e);  
            throw e;  
        }  
         
        log.info("method_param:" + method_param);
        log.info(packages + "." + monthName);  
        log.info("monthRemark:" + monthRemark);  
        //这里有点纠结 就是不好判断第一个object元素的类型 只好通过  方法描述来 做一一  转型感觉 这里 有点麻烦 可能是我对 aop不太了解  希望懂的高手在回复评论里给予我指点  
        //有没有更好的办法来记录操作参数  因为参数会有 实体类 或者javabean这种参数怎么把它里面的数据都解析出来?  
        return object;  
    }  
  
    // 方法运行出现异常时调用    
    // @AfterThrowing(pointcut = "execution(* com.wssys.controller.*(..))",  
    // throwing = "ex")  
    public void afterThrowing(Exception ex) {  
        System.out.println("afterThrowing");  
        System.out.println(ex);  
    }  
  
    // 获取方法的中文备注____用于记录用户的操作日志描述  
    public static String getMthodRemark(ProceedingJoinPoint joinPoint)  
            throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
  
        Class targetClass = Class.forName(targetName);  
        Method[] method = targetClass.getMethods();  
        String methode = "";  
        for (Method m : method) {  
            if (m.getName().equals(methodName)) {  
                Class[] tmpCs = m.getParameterTypes();  
                if (tmpCs.length == arguments.length) {  
                    MethodLog methodCache = m.getAnnotation(MethodLog.class);  
                    if (methodCache != null) {  
                        methode = methodCache.remark();  
                    }  
                    break;  
                }  
            }  
        }  
        return methode;  
    }  
}
